"""
@author: 江同学呀
@file: range_field.py
@date: 2024/7/27 20:20
@desc:
    https://www.elastic.co/guide/en/elasticsearch/reference/7.17/range.html

    Range types, such as long_range, double_range, date_range, and ip_range.
    范围类型，例如 long_range 、 double_range 、 date_range 和 ip_range 。
"""
import datetime
from abc import ABC
from typing import Type, Union, Dict

from espc.common.field_common import Range
from espc.orm.model.base.base import _Base
from espc.orm.model.mapping.field.base_field.base_field import _BaseField
from espc.orm.model.mapping.field.field_attribute import BoostAttribute, IndexAttribute, StoreAttribute, CoerceAttribute
from espc.utils.build_add_attr import build_add_attr


class IntegerRangeField(
    _BaseField, CoerceAttribute, BoostAttribute, IndexAttribute, StoreAttribute, ABC
):
    """
    带符号的32位整数范围 字段

    A range of signed 32-bit integers with a minimum value of -231 and maximum of 231-1.
    带符号的 32 位整数范围，最小值为 ，最大值为 -2^31 2^31-1 。
    """
    _field_type: str = "integer_range"

    def __init__(
            self, field_name: str = None, value: Dict[Union[Range, str], int] = None,
            default: Dict[Union[Range, str], int] = None, coerce: bool = None, boost: float = None, index: bool = None,
            store: bool = None,
    ):
        super().__init__(
            field_name=field_name, value=value, default=default, coerce=coerce, boost=boost, index=index, store=store
        )
        return

    def __get__(
            self, instance: _Base, owner: Type["IntegerRangeField"]
    ) -> Union["IntegerRangeField", Dict[Union[Range, str], int]]:
        return super(IntegerRangeField, self).__get__(instance=instance, owner=owner)

    def __set__(self, instance, value: Dict[Union[Range, str], int]):
        _value: Dict[str, int] = {k.value if isinstance(k, Range) else k: v for k, v in value.items()}
        super(IntegerRangeField, self).__set__(instance=instance, value=_value)
        return

    @property
    def value(self) -> Dict[Union[Range, str], int]:
        return self._value

    @value.setter
    def value(self, value: Dict[Union[Range, str], int]):
        self._value: Dict[Union[Range, str], int] = value
        return

    @build_add_attr
    def _build(self) -> Dict:
        mapping: Dict = {
            "type": self._field_type
        }
        return mapping


class FloatRangeField(
    _BaseField, CoerceAttribute, BoostAttribute, IndexAttribute, StoreAttribute, ABC
):
    """
    单精度32位IEEE754浮点值范围 字段

    A range of single-precision 32-bit IEEE 754 floating point values.
    单精度 32 位 IEEE 754 浮点值范围。
    """
    _field_type: str = "float_range"

    def __init__(
            self, field_name: str = None, value: Dict[Union[Range, str], float] = None,
            default: Dict[Union[Range, str], float] = None, coerce: bool = None, boost: float = None,
            index: bool = None, store: bool = None,
    ):
        super().__init__(
            field_name=field_name, value=value, default=default, coerce=coerce, boost=boost, index=index, store=store
        )
        return

    def __get__(
            self, instance: _Base, owner: Type["FloatRangeField"]
    ) -> Union["FloatRangeField", Dict[Union[Range, str], float]]:
        return super(FloatRangeField, self).__get__(instance=instance, owner=owner)

    def __set__(self, instance, value: Dict[Union[Range, str], float]):
        _value: Dict[str, float] = {k.value if isinstance(k, Range) else k: v for k, v in value.items()}
        super(FloatRangeField, self).__set__(instance=instance, value=_value)
        return

    @property
    def value(self) -> Dict[Union[Range, str], float]:
        return self._value

    @value.setter
    def value(self, value: Dict[Union[Range, str], float]):
        self._value: Dict[Union[Range, str], float] = value
        return

    @build_add_attr
    def _build(self) -> Dict:
        mapping: Dict = {
            "type": self._field_type
        }
        return mapping


class LongRangeField(
    _BaseField, CoerceAttribute, BoostAttribute, IndexAttribute, StoreAttribute, ABC
):
    """
    带符号的64位整数范围 字段

    A range of signed 64-bit integers with a minimum value of -263 and maximum of 263-1.
    带符号的 64 位整数范围，最小值为 -263 263-1 。
    """
    _field_type: str = "long_range"

    def __init__(
            self, field_name: str = None, value: Dict[Union[Range, str], int] = None,
            default: Dict[Union[Range, str], int] = None, coerce: bool = None, boost: float = None, index: bool = None,
            store: bool = None,
    ):
        super().__init__(
            field_name=field_name, value=value, default=default, coerce=coerce, boost=boost, index=index, store=store
        )
        return

    def __get__(
            self, instance: _Base, owner: Type["LongRangeField"]
    ) -> Union["LongRangeField", Dict[Union[Range, str], int]]:
        return super(LongRangeField, self).__get__(instance=instance, owner=owner)

    def __set__(self, instance, value: Dict[Union[Range, str], int]):
        _value: Dict[str, int] = {k.value if isinstance(k, Range) else k: v for k, v in value.items()}
        super(LongRangeField, self).__set__(instance=instance, value=_value)
        return

    @property
    def value(self) -> Dict[Union[Range, str], int]:
        return self._value

    @value.setter
    def value(self, value: Dict[Union[Range, str], int]):
        self._value: Dict[Union[Range, str], int] = value
        return

    @build_add_attr
    def _build(self) -> Dict:
        mapping: Dict = {
            "type": self._field_type
        }
        return mapping


class DoubleRangeField(
    _BaseField, CoerceAttribute, BoostAttribute, IndexAttribute, StoreAttribute, ABC
):
    """
    双精度64位IEEE754浮点值范围 字段

    A range of double-precision 64-bit IEEE 754 floating point values.
    双精度 64 位 IEEE 754 浮点值范围。
    """
    _field_type: str = "double_range"

    def __init__(
            self, field_name: str = None, value: Dict[Union[Range, str], float] = None,
            default: Dict[Union[Range, str], float] = None, coerce: bool = None, boost: float = None,
            index: bool = None, store: bool = None,
    ):
        super().__init__(
            field_name=field_name, value=value, default=default, coerce=coerce, boost=boost, index=index, store=store
        )
        return

    def __get__(
            self, instance: _Base, owner: Type["DoubleRangeField"]
    ) -> Union["DoubleRangeField", Dict[Union[Range, str], float]]:
        return super(DoubleRangeField, self).__get__(instance=instance, owner=owner)

    def __set__(self, instance, value: Dict[Union[Range, str], float]):
        _value: Dict[str, float] = {k.value if isinstance(k, Range) else k: v for k, v in value.items()}
        super(DoubleRangeField, self).__set__(instance=instance, value=_value)
        return

    @property
    def value(self) -> Dict[Union[Range, str], float]:
        return self._value

    @value.setter
    def value(self, value: Dict[Union[Range, str], float]):
        self._value: Dict[Union[Range, str], float] = value
        return

    @build_add_attr
    def _build(self) -> Dict:
        mapping: Dict = {
            "type": self._field_type
        }
        return mapping


class DateRangeField(
    _BaseField, CoerceAttribute, BoostAttribute, IndexAttribute, StoreAttribute, ABC
):
    """
    日期范围 字段

    A range of date values. Date ranges support various date formats through the format mapping parameter. Regardless
    of the format used, date values are parsed into an unsigned 64-bit integer representing milliseconds since the Unix
    epoch in UTC. Values containing the now date math expression are not supported.
    值范围 date 。日期范围通过 format mapping 参数支持各种日期格式。无论使用何种格式，日期值都会被解析为一个无符号的 64 位整数，表示自 UTC
    中 Unix 纪元以来的毫秒数。不支持包含日期数学表达式的值 now 。
    """
    _field_type: str = "date_range"

    def __init__(
            self, field_name: str = None, value: Dict[Union[Range, str], Union[str, datetime.datetime]] = None,
            default: Dict[Union[Range, str], Union[str, datetime.datetime]] = None, coerce: bool = None, 
            boost: float = None, index: bool = None, store: bool = None,
    ):
        super().__init__(
            field_name=field_name, value=value, default=default, coerce=coerce, boost=boost, index=index, store=store
        )
        return

    def __get__(
            self, instance: _Base, owner: Type["DateRangeField"]
    ) -> Union["DateRangeField", Dict[Union[Range, str], Union[str, datetime.datetime]]]:
        return super(DateRangeField, self).__get__(instance=instance, owner=owner)

    def __set__(self, instance, value: Dict[Union[Range, str], Union[str, datetime.datetime]]):
        _value: Dict[str, str] = {
            k.value if isinstance(k, Range) else k:
                v.strftime("%Y-%m-%d %H:%M:%S") if isinstance(v, datetime.datetime) else (
                    v.strftime("%Y-%m-%d") if isinstance(v, datetime.date) else v
                )
            for k, v in value.items()
        }
        super(DateRangeField, self).__set__(instance=instance, value=_value)
        return

    @property
    def value(self) -> Dict[Union[Range, str], Union[str, datetime.datetime]]:
        return self._value

    @value.setter
    def value(self, value: Dict[Union[Range, str], Union[str, datetime.datetime]]):
        self._value: Dict[Union[Range, str], Union[str, datetime.datetime]] = value
        return

    @build_add_attr
    def _build(self) -> Dict:
        mapping: Dict = {
            "type": self._field_type
        }
        return mapping


class IPRangeField(
    _BaseField, CoerceAttribute, BoostAttribute, IndexAttribute, StoreAttribute, ABC
):
    """
    IP范围 字段

    A range of ip values supporting either IPv4 or IPv6 (or mixed) addresses.
    支持 IPv4 或 IPv6（或混合）地址的 IP 值范围。
    """
    _field_type: str = "ip_range"

    def __init__(
            self, field_name: str = None, value: Dict[Union[Range, str], str] = None,
            default: Dict[Union[Range, str], str] = None, coerce: bool = None, boost: float = None, index: bool = None,
            store: bool = None,
    ):
        super().__init__(
            field_name=field_name, value=value, default=default, coerce=coerce, boost=boost, index=index, store=store
        )
        return

    def __get__(
            self, instance: _Base, owner: Type["IPRangeField"]
    ) -> Union["IPRangeField", Dict[Union[Range, str], str]]:
        return super(IPRangeField, self).__get__(instance=instance, owner=owner)

    def __set__(self, instance, value: Dict[Union[Range, str], str]):
        _value: Dict[str, str] = {k.value if isinstance(k, Range) else k: v for k, v in value.items()}
        super(IPRangeField, self).__set__(instance=instance, value=_value)
        return

    @property
    def value(self) -> Dict[Union[Range, str], str]:
        return self._value

    @value.setter
    def value(self, value: Dict[Union[Range, str], str]):
        self._value: Dict[Union[Range, str], str] = value
        return

    @build_add_attr
    def _build(self) -> Dict:
        mapping: Dict = {
            "type": self._field_type
        }
        return mapping






